package com.danikula.videocache.sourcestorage;

import ohos.app.Context;
import ohos.data.DatabaseHelper;
import ohos.data.rdb.*;
import ohos.data.resultset.ResultSet;

import com.danikula.videocache.SourceInfo;

import static com.danikula.videocache.Preconditions.checkAllNotNull;
import static com.danikula.videocache.Preconditions.checkNotNull;

/**
 * Database based {@link SourceInfoStorage}.
 *
 * @author Alexey Danilov (danikula@gmail.com).
 */
class DatabaseSourceInfoStorage extends DatabaseHelper implements SourceInfoStorage {

    private static final String TABLE = "SourceInfo";
    private static final String COLUMN_ID = "_id";
    private static final String COLUMN_URL = "url";
    private static final String COLUMN_LENGTH = "length";
    private static final String COLUMN_MIME = "mime";
    private static final String[] ALL_COLUMNS = new String[]{COLUMN_ID, COLUMN_URL, COLUMN_LENGTH, COLUMN_MIME};
    private static final String CREATE_SQL =
            "CREATE TABLE " + TABLE + " (" +
                    COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
                    COLUMN_URL + " TEXT NOT NULL," +
                    COLUMN_MIME + " TEXT," +
                    COLUMN_LENGTH + " INTEGER" +
                    ");";

    private final RdbStore myRdbStore;
    private final StoreConfig config = StoreConfig.newDefaultConfig("AndroidVideoCache.db");
//
//    static class myRdbOpenCallback extends RdbOpenCallback {
//
//        @Override
//        public void onCreate(RdbStore rdbStore) {
//            checkNotNull(rdbStore);
//            rdbStore.executeSql(CREATE_SQL);
//        }
//
//        @Override
//        public void onUpgrade(RdbStore rdbStore, int i, int i1) {
//            throw new IllegalStateException("Should not be called. There is no any migration");
//        }
//    }

    private static final RdbOpenCallback callback = new RdbOpenCallback() {
        @Override
        public void onCreate(RdbStore rdbStore) {
            checkNotNull(rdbStore);
            rdbStore.executeSql(CREATE_SQL);
        }

        @Override
        public void onUpgrade(RdbStore rdbStore, int i, int i1) {
            throw new IllegalStateException("Should not be called. There is no any migration");
        }
    };

    DatabaseSourceInfoStorage(Context context) {
        super(context);
        DatabaseHelper helper = new DatabaseHelper(context);
        this.myRdbStore = helper.getRdbStore(config, 1, callback,null);
        checkNotNull(context);
    }

    @Override
    public SourceInfo get(String url) {
        checkNotNull(url);
        ResultSet cursor = null;
        try{
            RdbPredicates predicates = new RdbPredicates(TABLE);
            predicates.equalTo(COLUMN_URL, url);
            cursor = this.myRdbStore.query(predicates, null);
            return cursor == null || !cursor.goToFirstRow() ? null : convert(cursor);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

    @Override
    public void put(String url, SourceInfo sourceInfo) {
        checkAllNotNull(url, sourceInfo);
        SourceInfo sourceInfoFromDb = get(url);
        boolean exist = sourceInfoFromDb != null;
        RdbPredicates predicates = new RdbPredicates(TABLE);
        if (exist) {
            predicates.contains(COLUMN_URL, url);
            this.myRdbStore.update(convert(sourceInfo), predicates);
        } else {
            this.myRdbStore.insert(TABLE, convert(sourceInfo));
        }
    }

    @Override
    public void release() {
        this.myRdbStore.close();
    }

    private SourceInfo convert(ResultSet cursor) {
        return new SourceInfo(
                cursor.getString(cursor.getColumnIndexForName(COLUMN_URL)),
                cursor.getLong(cursor.getColumnIndexForName(COLUMN_LENGTH)),
                cursor.getString(cursor.getColumnIndexForName(COLUMN_MIME))
        );
    }

    private ValuesBucket convert(SourceInfo sourceInfo) {
        ValuesBucket values = new ValuesBucket();
        values.putString(COLUMN_URL, sourceInfo.url);
        values.putLong(COLUMN_LENGTH, sourceInfo.length);
        values.putString(COLUMN_MIME, sourceInfo.mime);
        return values;
    }
}